package net.wsnetwork.jawa.common;

import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Represents cache information for an HTTP object.
 *
 * @author cairns@colorado.edu (Brian Cairns)
 */
public final class CacheControlInfo {
    private static final long DEFAULT_MAX_AGE = 120L;
    private static final Pattern MAX_AGE_PATTERN = Pattern.compile("max\\-age\\=([0-9]+)");

    private final boolean cacheAllowed;
    private final boolean storeAllowed;
    private final Date expires;

    public CacheControlInfo(String cacheHeader) {
        if (cacheHeader == null) {
            cacheAllowed = false;
            storeAllowed = false;
            expires = null;
        } else if (cacheHeader.contains("no-store")) {
            cacheAllowed = false;
            storeAllowed = false;
            expires = null;
        } else if (cacheHeader.contains("private") || cacheHeader.contains("no-cache")) {
            cacheAllowed = false;
            storeAllowed = true;
            expires = null;
        } else {
            cacheAllowed = true;
            storeAllowed = true;
            Matcher maxAgeMatcher = MAX_AGE_PATTERN.matcher(cacheHeader);
            long maxAge = DEFAULT_MAX_AGE;
            if (maxAgeMatcher.find()) {
                String maxAgeString = maxAgeMatcher.group(1);
                maxAge = Integer.parseInt(maxAgeString);
            }
            expires = new Date(System.currentTimeMillis() + maxAge * 1000);
        }
    }

    /**
     * Returns {@code true} if the object may be stored in the cache.
     */
    public boolean isCacheable() {
        return cacheAllowed && storeAllowed;
    }

    /**
     * Returns {@code true} if the object's cache entry has expired.
     */
    public boolean hasExpired() {
        Date now = new Date();
        return isCacheable() && expires.before(now);
    }

    /**
     * Returns an HTTP cache header that is appropriate for the object.
     */
    public String getCacheHeader() {
        if (!storeAllowed) {
            return "no-store";
        } else if (!cacheAllowed) {
            return "no-cache";
        } else {
            Date now = new Date();
            long maxAge = (expires.getTime() - now.getTime()) / 1000;
            if (maxAge < 0) { maxAge = 0; }
            return "max-age=" + maxAge + "; must-revalidate";
        }
    }
}
